package com.cooldatasoft.taskManager.user.gui;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;

import com.cooldatasoft.domain.model.Project;
import com.cooldatasoft.domain.model.User;
import com.cooldatasoft.domain.model.UserProjectRoles;
import com.cooldatasoft.domain.service.ProjectsService;
import com.cooldatasoft.domain.service.RolesService;
import com.cooldatasoft.domain.service.UserProjectRolesService;
import com.cooldatasoft.domain.service.UserService;
import com.cooldatasoft.taskManager.MainPage;
import com.vaadin.annotations.AutoGenerated;
import com.vaadin.data.Item;
import com.vaadin.data.util.BeanItem;
import com.vaadin.data.validator.StringLengthValidator;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Component;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.DefaultFieldFactory;
import com.vaadin.ui.Field;
import com.vaadin.ui.Form;
import com.vaadin.ui.GridLayout;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.NativeButton;
import com.vaadin.ui.PopupDateField;
import com.vaadin.ui.TextArea;
import com.vaadin.ui.TextField;
import com.vaadin.ui.TwinColSelect;
import com.vaadin.ui.VerticalLayout;

@Configurable(preConstruction=true)
public class AddProjectView extends CustomComponent {

	@AutoGenerated
	private VerticalLayout mainLayout;
	@AutoGenerated
	private HorizontalLayout buttonsLayout;
	@AutoGenerated
	private NativeButton resetBtn;
	@AutoGenerated
	private NativeButton submitBtn;
	@AutoGenerated
	private HorizontalLayout formLayout;
	@AutoGenerated
	private VerticalLayout selectUserForm;
	@AutoGenerated
	private TwinColSelect selectUserList;
	@AutoGenerated
	private TwinColSelect selectManagerLists;
	@AutoGenerated
	private VerticalLayout projectFormLayout;
	
	@Autowired
	private UserService userService;
	@Autowired
	private UserProjectRolesService userProjectRolesService;
	@Autowired
	private ProjectsService projectService;
	@Autowired
	private RolesService roleService;

	private static final long serialVersionUID = 1L;
	private Form form;
	private Project project;
	private BeanItem<Project> projectItem;
	private List<User> selectedUser;
	private List<User> selectedManagers;
	private MainPage mainPage;

	public AddProjectView() {
		buildMainLayout();
		setCompositionRoot(mainLayout);
		customizeProjectForm();
		customizeSelector();
		customizeButtons();
		
		selectedManagers = new ArrayList<User>();
		selectedUser = new ArrayList<User>();
	}

	private void customizeButtons() {
		submitBtn.addListener(new Button.ClickListener() {
			
			private static final long serialVersionUID = 1L;

			@SuppressWarnings("unchecked")
			@Override
			public void buttonClick(ClickEvent event) {
				form.commit();
				project.setStatus("begin");
				Long projectId = projectService.insertProjects(project);			
				
				for(Integer i : (Collection<Integer>) selectUserList.getValue()) {
					User user = (User) selectUserList.getItem(i).getItemProperty("user").getValue();
					selectedUser.add(user);
				}
				
				for(Integer i : (Collection<Integer>) selectManagerLists.getValue()) {
					User manager = (User) selectManagerLists.getItem(i).getItemProperty("user").getValue();
					selectedManagers.add(manager);
				}
				
				for (User user : selectedUser) {
					if (user != null) {
						UserProjectRoles upr = new UserProjectRoles();
						upr.setIdProject(projectService.getProjectsByIdProject(projectId));
						upr.setIdRole(roleService.getRoleById(2L));
						upr.setIdUser(user);
						
						userProjectRolesService.insertUserProjectRoles(upr);
					}
				}
				
				for (User manager : selectedManagers) {
					if (manager != null) {
						UserProjectRoles upr = new UserProjectRoles();
						upr.setIdProject(projectService.getProjectsByIdProject(projectId));
						upr.setIdRole(roleService.getRoleById(1L));
						upr.setIdUser(manager);		
						
						userProjectRolesService.insertUserProjectRoles(upr);
					}
				}
				getWindow().getParent().showNotification("New project succesfully created");
				(getWindow().getParent()).removeWindow(getWindow());
				
				mainPage.addProject(project);
			}
		});
		
		resetBtn.addListener(new Button.ClickListener() {
			
			private static final long serialVersionUID = 1L;

			@Override
			public void buttonClick(ClickEvent event) {
				form.discard();				
			}
		});
		
	}

	private void customizeSelector() {
		selectUserList.addContainerProperty("user", User.class, null);
		selectManagerLists.addContainerProperty("user", User.class, null);
		
		List<User> users = new ArrayList<User>();
		users.addAll(userService.getAllUser());
		
		for(User user : users) {
			Object userObject = selectUserList.addItem();
			Object managerObject = selectManagerLists.addItem();
			
			selectUserList.getItem(userObject).getItemProperty("user").setValue(user);
			selectUserList.setItemCaption(userObject, user.getName() + " " + user.getSurname());
			selectManagerLists.getItem(managerObject).getItemProperty("user").setValue(user);
			selectManagerLists.setItemCaption(managerObject, user.getName() + " " + user.getSurname());
		}
		selectManagerLists.setMultiSelect(true);
		selectUserList.setMultiSelect(true);
		selectManagerLists.setImmediate(true);
		selectUserList.setImmediate(true);
		selectManagerLists.setNullSelectionAllowed(true);
		selectUserList.setNullSelectionAllowed(true);
	}

	private void customizeProjectForm() {
		project = new Project();
		projectItem = new BeanItem<Project>(project);
		form = new FormWithComplexLayout(projectItem);
		
		form.setCaption("Fill project data");
		form.setWriteThrough(false);
		form.setInvalidCommitted(false);

		projectFormLayout.addComponent(form);		
	}

	public class FormWithComplexLayout extends Form {

		private static final long serialVersionUID = 1L;
		private GridLayout ourLayout;

		public FormWithComplexLayout(BeanItem<Project> projectItem) {
			setCaption("Registration form");

			ourLayout = new GridLayout(2, 4);
			ourLayout.setMargin(true, false, false, true);
			ourLayout.setSpacing(true);
			setLayout(ourLayout);

			setWriteThrough(false); 
			setInvalidCommitted(false); 

			setFormFieldFactory(new ProjectFieldFactory());
			setItemDataSource(projectItem); 

			setVisibleItemProperties(Arrays.asList(new String[] { "name", "description", "platform", "created", "finished", "status" }));
		}

		@Override
		protected void attachField(Object propertyId, Field field) {
			if (propertyId.equals("name")) {
				ourLayout.addComponent(field, 0, 0);
			} else if (propertyId.equals("platform")) {
				ourLayout.addComponent(field, 1, 0);
			} else if (propertyId.equals("description")) {
				ourLayout.addComponent(field, 0, 1, 1, 1);
			} else if (propertyId.equals("created")) {
				ourLayout.addComponent(field, 0, 2);
			} else if (propertyId.equals("finished")) {
				ourLayout.addComponent(field, 1, 2);
			} else if (propertyId.equals("status")) {
				ourLayout.addComponent(field, 0,3,1,3);
		}
	}
	
	private class ProjectFieldFactory extends DefaultFieldFactory {

		private static final long serialVersionUID = 1L;
		private static final String COMMON_FIELD_WIDTH = "150px";
		private static final String DOUBLE_FIELD_WIDTH = "320px";

		@Override
		public Field createField(Item item, Object propertyId, Component uiContext) {
			Field f;	
			
			if ("description".equals(propertyId)) {
				f = createTextAreaField(propertyId);
			} else if ("created".equals(propertyId)) {
				f = createDateField(propertyId);
			} else if ("finished".equals(propertyId)) {
				f = createDateField(propertyId);
			} else {
				f = super.createField(item, propertyId, uiContext);
			}            

			if ("name".equals(propertyId)) {
				TextField tf = (TextField) f;
				tf.setNullRepresentation("");
				tf.setRequired(true);
				tf.setImmediate(true);
				tf.setRequiredError("Please enter a project name");
				tf.setWidth(COMMON_FIELD_WIDTH);
				tf.addValidator(new StringLengthValidator("Name must be 3-25 characters", 3, 50, false));
			} else if ("platform".equals(propertyId)) {
				TextField tf = (TextField) f;
				tf.setNullRepresentation("");
				tf.setRequired(true);
				tf.setImmediate(true);
				tf.setRequiredError("Please enter a project platform");
				tf.setWidth(COMMON_FIELD_WIDTH);
				tf.addValidator(new StringLengthValidator("Platform must be 3-50 characters", 3, 50, false));
			} else if ("description".equals(propertyId)) {
				TextArea ta = (TextArea) f;
				ta.setNullRepresentation("");
				ta.setImmediate(true);
				ta.setRequired(true);
				ta.setRequiredError("Please enter project description");
				ta.setWidth(DOUBLE_FIELD_WIDTH);
			} else if("status".equals(propertyId)) {
				TextField tf = (TextField) f;
				tf.setNullRepresentation("");
				tf.setImmediate(true);
				tf.setWidth(COMMON_FIELD_WIDTH);
				tf.setEnabled(false);
				tf.setInputPrompt("begin");
			} else if ("created".equals(propertyId)) {
				PopupDateField df = (PopupDateField) f;
				df.setCaption("Project start date");
				df.setRequired(true);
				df.setWidth(COMMON_FIELD_WIDTH);
				df.setResolution(PopupDateField.RESOLUTION_DAY);
			} else if ("finished".equals(propertyId)) {
				PopupDateField df = (PopupDateField) f;
				df.setCaption("Project end date");
				df.setRequired(true);
				df.setWidth(COMMON_FIELD_WIDTH);
				df.setResolution(PopupDateField.RESOLUTION_DAY);
			}
			return f;
		}

		private TextArea createTextAreaField(Object propertyId) {
			TextArea ta = new TextArea();
			ta.setCaption(DefaultFieldFactory.createCaptionByPropertyId(propertyId));
			return ta;
		}
		
		private PopupDateField createDateField(Object propertyId) {
			PopupDateField df = new PopupDateField();
			return df;
		}
	}
}

	@AutoGenerated
	private VerticalLayout buildMainLayout() {
		// common part: create layout
		mainLayout = new VerticalLayout();
		mainLayout.setImmediate(false);
		mainLayout.setWidth("100%");
		mainLayout.setHeight("100%");
		mainLayout.setMargin(false);
		
		// top-level component properties
		setWidth("100.0%");
		setHeight("100.0%");
		
		// formLayout
		formLayout = buildFormLayout();
		mainLayout.addComponent(formLayout);
		
		// buttonsLayout
		buttonsLayout = buildButtonsLayout();
		mainLayout.addComponent(buttonsLayout);
		
		return mainLayout;
	}

	@AutoGenerated
	private HorizontalLayout buildFormLayout() {
		// common part: create layout
		formLayout = new HorizontalLayout();
		formLayout.setImmediate(false);
		formLayout.setWidth("100.0%");
		formLayout.setHeight("-1px");
		formLayout.setMargin(false);
		
		// projectFormLayout
		projectFormLayout = new VerticalLayout();
		projectFormLayout.setImmediate(false);
		projectFormLayout.setWidth("100.0%");
		projectFormLayout.setHeight("100.0%");
		projectFormLayout.setMargin(true);
		projectFormLayout.setSpacing(true);
		formLayout.addComponent(projectFormLayout);
		
		// selectUserForm
		selectUserForm = buildSelectUserForm();
		formLayout.addComponent(selectUserForm);
		
		return formLayout;
	}

	@AutoGenerated
	private VerticalLayout buildSelectUserForm() {
		// common part: create layout
		selectUserForm = new VerticalLayout();
		selectUserForm.setImmediate(false);
		selectUserForm.setWidth("100.0%");
		selectUserForm.setHeight("100.0%");
		selectUserForm.setMargin(true);
		selectUserForm.setSpacing(true);
		
		// selectManagerLists
		selectManagerLists = new TwinColSelect();
		selectManagerLists.setCaption("Assign managers to project");
		selectManagerLists.setImmediate(false);
		selectManagerLists.setWidth("-1px");
		selectManagerLists.setHeight("-1px");
		selectUserForm.addComponent(selectManagerLists);
		selectUserForm.setComponentAlignment(selectManagerLists, new Alignment(
				48));
		
		// selectUserList
		selectUserList = new TwinColSelect();
		selectUserList.setCaption("Assign programmers to project");
		selectUserList.setImmediate(false);
		selectUserList.setWidth("-1px");
		selectUserList.setHeight("-1px");
		selectUserForm.addComponent(selectUserList);
		selectUserForm.setComponentAlignment(selectUserList, new Alignment(48));
		
		return selectUserForm;
	}

	@AutoGenerated
	private HorizontalLayout buildButtonsLayout() {
		// common part: create layout
		buttonsLayout = new HorizontalLayout();
		buttonsLayout.setImmediate(false);
		buttonsLayout.setWidth("-1px");
		buttonsLayout.setHeight("-1px");
		buttonsLayout.setMargin(true);
		buttonsLayout.setSpacing(true);
		
		// submitBtn
		submitBtn = new NativeButton();
		submitBtn.setCaption("Submit");
		submitBtn.setImmediate(true);
		submitBtn.setWidth("-1px");
		submitBtn.setHeight("-1px");
		submitBtn.setStyleName("defaultBtn");
		buttonsLayout.addComponent(submitBtn);
		
		// resetBtn
		resetBtn = new NativeButton();
		resetBtn.setCaption("Reset");
		resetBtn.setImmediate(true);
		resetBtn.setWidth("-1px");
		resetBtn.setHeight("-1px");
		resetBtn.setStyleName("defaultBtn");
		buttonsLayout.addComponent(resetBtn);
		
		return buttonsLayout;
	}
	
	public MainPage getMainPage() {
		return mainPage;
	}

	public void setMainPage(MainPage mainPage) {
		this.mainPage = mainPage;
	}

}
